import { createContext, useContext, useRef, useState, useEffect } from 'react';
import { useCanvasKit } from './CanvasKitContext';

const TextRenderingContext = createContext();

export const useTextRendering = () => {
  const context = useContext(TextRenderingContext);
  if (!context) {
    throw new Error('useTextRendering must be used within a TextRenderingProvider');
  }
  return context;
};

export const TextRenderingProvider = ({ children }) => {
  const {
    canvasKitStatus,
    canvasKitInstance,
    fontsLoaded,
    availableFonts,
    fontManager,
    getTypefaceFromCache,
    getAvailableWeightsForFamily
  } = useCanvasKit();

  // Font rendering parameters
  const [fontSize, setFontSize] = useState(16);
  // Fixed letter spacing for all font families and sizes
  const letterSpacing = -0.7;
  const [selectedFont, setSelectedFont] = useState('');
  const [fontVariant, setFontVariant] = useState('regular');
  
  // Available options for UI
  const [availableFontVariants, setAvailableFontVariants] = useState([]);

  // Typography settings (fixed for optimal rendering)
  const hinting = 'full';
  const edging = 'subpixelantialias'; 
  const subpixel = true;

  // Current font instance
  const currentFontRef = useRef(null);

  // Helper functions to convert between fontVariant and weight/style
  const getWeightAndStyleFromVariant = (variant) => {
    switch (variant) {
      case 'regular':
        return { weight: 400, style: 'normal' };
      case 'italic':
        return { weight: 400, style: 'italic' };
      case 'bold':
        return { weight: 700, style: 'normal' };
      default:
        return { weight: 400, style: 'normal' };
    }
  };

  const getVariantFromWeightAndStyle = (weight, style) => {
    if (weight === 700 && style === 'normal') return 'bold';
    if (weight === 400 && style === 'italic') return 'italic';
    return 'regular';
  };

  // Helper function to calculate line height based on line break type
  const getLineHeightForBreakType = (breakType) => {
    if (breakType === '\r\n') {
      return fontSize * 1.5; // Enter key (paragraph break)
    } else if (breakType === '\n') {
      return fontSize * 1.0; // Shift+Enter (line break)
    }
    return fontSize * 1.2; // Default fallback
  };

  // Helper function to analyze text and get line break information
  const analyzeTextLineBreaks = (text) => {
    if (!text) return [];
    
    const lines = [];
    const parts = text.split(/(\r\n|\n)/);
    let currentLine = '';
    
    for (let i = 0; i < parts.length; i++) {
      const part = parts[i];
      if (part === '\r\n' || part === '\n') {
        lines.push({
          text: currentLine,
          breakType: part,
          lineHeight: getLineHeightForBreakType(part)
        });
        currentLine = '';
      } else {
        currentLine += part;
      }
    }
    
    // Add the last line if it doesn't end with a line break
    if (currentLine.length > 0 || lines.length === 0) {
      lines.push({
        text: currentLine,
        breakType: null, // No line break after this line
        lineHeight: fontSize * 1.2 // Default line height
      });
    }
    
    return lines;
  };

  // Set up available fonts and default selection when fonts are loaded
  useEffect(() => {
    if (fontsLoaded && availableFonts.length > 0 && !selectedFont) {
      setSelectedFont(availableFonts[0].value);
    }
  }, [fontsLoaded, availableFonts, selectedFont]);

  // Update available font variants when selected font changes
  useEffect(() => {
    if (selectedFont && fontsLoaded) {
      const weights = getAvailableWeightsForFamily(selectedFont);
      
      // Create available variants based on available weights
      const variants = [];
      
      // Always add regular (400 normal)
      if (weights.includes(400)) {
        variants.push({ value: 'regular', name: 'Regular' });
      }
      
      // Add italic if 400 weight is available (assuming italic is available)
      if (weights.includes(400)) {
        variants.push({ value: 'italic', name: 'Italic' });
      }
      
      // Add bold if 700 weight is available
      if (weights.includes(700)) {
        variants.push({ value: 'bold', name: 'Bold' });
      }
      
      // If no variants available, add regular as fallback
      if (variants.length === 0) {
        variants.push({ value: 'regular', name: 'Regular' });
      }
      
      setAvailableFontVariants(variants);

      // Set default variant if current variant is not available
      const availableVariantValues = variants.map(v => v.value);
      if (!availableVariantValues.includes(fontVariant)) {
        setFontVariant(variants[0]?.value || 'regular');
      }
    }
  }, [selectedFont, fontsLoaded, fontVariant, getAvailableWeightsForFamily]);

  // Create font instance from typeface and size with typography settings
  const createCurrentFont = () => {
    if (!canvasKitInstance) {
      console.warn('CanvasKit not available for font creation');
      return null;
    }

    const { weight, style } = getWeightAndStyleFromVariant(fontVariant);
    const typeface = getTypefaceFromCache(selectedFont, weight, style);
    
    if (!typeface) {
      return createFallbackFont();
    }
    
    let font;
    try {
      // Try different ways to create the font
      if (canvasKitInstance.Font && typeof canvasKitInstance.Font === 'function') {
        font = new canvasKitInstance.Font(typeface, fontSize);
      } else if (canvasKitInstance.MakeFont) {
        font = canvasKitInstance.MakeFont(typeface, fontSize);
      } else {
        console.error('No Font constructor or MakeFont method available');
        return createFallbackFont();
      }
    } catch (error) {
      console.error('Failed to create font:', error);
      console.error('Typeface object:', typeface);
      return createFallbackFont();
    }
    
    if (!font) {
      console.error('Font creation returned null/undefined');
      return createFallbackFont();
    }
    
    // Apply typography settings if methods are available
    try {
      // Hinting control
      if (font.setHinting && canvasKitInstance.FontHinting) {
        const hintingValue = {
          'none': canvasKitInstance.FontHinting.None,
          'slight': canvasKitInstance.FontHinting.Slight,
          'normal': canvasKitInstance.FontHinting.Normal,
          'full': canvasKitInstance.FontHinting.Full
        }[hinting];
        if (hintingValue !== undefined) {
          font.setHinting(hintingValue);
        }
      }
      
      // Edging/anti-aliasing control
      if (font.setEdging && canvasKitInstance.FontEdging) {
        const edgingValue = {
          'alias': canvasKitInstance.FontEdging.Alias,
          'antialias': canvasKitInstance.FontEdging.AntiAlias,
          'subpixelantialias': canvasKitInstance.FontEdging.SubpixelAntiAlias
        }[edging];
        if (edgingValue !== undefined) {
          font.setEdging(edgingValue);
        }
      }
      
      // Subpixel positioning
      if (font.setSubpixel) {
        font.setSubpixel(subpixel);
      }
      
      // Linear metrics (affects kerning)
      if (font.setLinearMetrics) {
        font.setLinearMetrics(true); // Better for kerning
      }
      
      // Embedded bitmap text (can affect rendering quality)
      if (font.setEmbeddedBitmaps) {
        font.setEmbeddedBitmaps(false); // Use vector rendering
      }
      
    } catch (error) {
      console.warn('Some typography settings not available:', error);
    }
    
    return font;
  };

  // Create a fallback font using system fonts
  const createFallbackFont = () => {
    if (!canvasKitInstance) return null;
    
    try {
      // Try to create a font with null typeface (system default)
      if (canvasKitInstance.Font && typeof canvasKitInstance.Font === 'function') {
        const fallbackFont = new canvasKitInstance.Font(null, fontSize);
        return fallbackFont;
      } else if (canvasKitInstance.MakeFont) {
        const fallbackFont = canvasKitInstance.MakeFont(null, fontSize);
        return fallbackFont;
      } else {
        console.error('❌ No font creation methods available for fallback');
        return null;
      }
    } catch (error) {
      console.error('❌ Failed to create fallback font:', error);
      return null;
    }
  };

  // Create font when font parameters change
  useEffect(() => {
    if (!fontsLoaded || canvasKitStatus !== 'ready') return;
    
    const font = createCurrentFont();
    
    if (font) {
      currentFontRef.current = font;
    } else {
      console.warn('⚠️ Failed to create font, using fallback');
      currentFontRef.current = null;
    }
  }, [selectedFont, fontVariant, fontSize, fontsLoaded, canvasKitStatus]);

  // Helper function to get current font instance
  const getCurrentFont = () => {
    return currentFontRef.current;
  };

  // Helper function to measure text width
  const measureTextWidth = (text) => {
    const font = getCurrentFont();
    if (!font || !canvasKitInstance) return 0;
    
    try {
      const textBlob = canvasKitInstance.TextBlob.MakeFromText(text, font);
      const bounds = textBlob.getBounds();
      textBlob.delete();
      return bounds[2] - bounds[0]; // width = right - left
    } catch (error) {
      // console.warn(`Failed to measure text width [${text}]:`, error);
      return text.length * fontSize * 0.6; // Rough estimate
    }
  };

  const value = {
    // Font parameters
    fontSize,
    setFontSize,
    letterSpacing,
    selectedFont,
    setSelectedFont,
    fontVariant,
    setFontVariant,

    // Available options for UI
    availableFontVariants,

    // Typography settings (read-only)
    hinting,
    edging,
    subpixel,

    // Font utilities
    getCurrentFont,
    measureTextWidth,
    createCurrentFont,

    // Line height utilities
    getLineHeightForBreakType,
    analyzeTextLineBreaks,

    // Status
    isReady: fontsLoaded && canvasKitStatus === 'ready',

    // Refs for advanced usage
    currentFontRef,
  };

  return (
    <TextRenderingContext.Provider value={value}>
      {children}
    </TextRenderingContext.Provider>
  );
};
